package com.sskj.boom.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.SurfaceTexture;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.TextureView;
import android.view.View;

import com.sskj.boom.R;
import com.sskj.boom.bean.EscapeBean;
import com.sskj.boom.bean.GameStatus;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class BoomView extends View {
    private Canvas mCanvas;
    private float width;
    private float height;
    private float minYNum = 2;
    private float minXNum = 10000;//起初
    private float sectionNumX = 5;
    private float sectionNumY = 5;
    private float initDegreeX = 2;//初始x轴刻度最小单位
    private float initDegreeY = 1f;//初始y轴刻度最小单位
    private int nowTime = 0;//当前时间，毫秒
    private int paddingStart;
    private int paddingTop;
    private int paddingBottom;
    private int paddingEnd;
    private int klineNum = 100;//绘制的点数
    private int prepareTime = 6000;//准备时间

    private float boomValue;//爆炸点倍数
    private GameStatus gameStatus = GameStatus.NOSTATE;

    private float xSection = 100;
    private float ySection = 100;
    private Paint lineKPaint;
    private Paint lineStrokePaint;
    private Paint lineTextPaint;
    private Paint boomTextPaint;
    private Paint boomValuePaint;
    private Paint lineTextScalePaint;
    Context context;
    private float startX;
    private float startY;
    private float xLenth;
    private float yLenth;
    private Timer timer;
    private List<EscapeBean> escapeBeans = new ArrayList<>();
    private BoomListener boomListener;
    private int bgColor;
    private boolean canDraw = true;
    private Timer timerDraw;
    private boolean isFirst = true;

    public void setBoomListener(BoomListener boomListener) {
        this.boomListener = boomListener;
    }

    public BoomView(Context context) {
        super(context);
        this.context = context;
        init();
    }


    public BoomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    public BoomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init();
    }

    private void init() {
        lineKPaint = new Paint();
        lineKPaint.setAntiAlias(true);
        lineStrokePaint = new Paint();
        lineStrokePaint.setAntiAlias(true);
        lineTextPaint = new Paint();
        lineTextPaint.setAntiAlias(true);
        boomTextPaint = new Paint();
        boomTextPaint.setAntiAlias(true);
        boomTextPaint.setTextSize(60);
        boomTextPaint.setColor(ContextCompat.getColor(context, R.color.boom_line_boom));
        boomTextPaint.setTextAlign(Paint.Align.CENTER);
        boomValuePaint = new Paint();
        boomValuePaint.setAntiAlias(true);
        boomValuePaint.setTextSize(40);
        boomValuePaint.setColor(ContextCompat.getColor(context, R.color.boom_line_text));
        boomValuePaint.setTextAlign(Paint.Align.CENTER);
        lineTextScalePaint = new Paint();
        lineTextScalePaint.setAntiAlias(true);
        lineTextScalePaint.setTextSize(60);
        lineTextScalePaint.setColor(Color.WHITE);
        lineTextScalePaint.setTextAlign(Paint.Align.CENTER);
        lineTextPaint.setTextSize(30);
        lineTextPaint.setTextAlign(Paint.Align.CENTER);
        lineTextPaint.setColor(ContextCompat.getColor(context, R.color.boom_line_text));
        lineKPaint.setColor(ContextCompat.getColor(context, R.color.boom_line_k));
        lineKPaint.setStyle(Paint.Style.STROKE);
        lineKPaint.setStrokeWidth(5);
        lineStrokePaint.setColor(ContextCompat.getColor(context, R.color.boom_line_stroke));

    }

    public void setBgColor(int color) {
        bgColor = color;
    }

    /**
     * 游戏开始
     */
    public void gameStart() {
        if (gameStatus == GameStatus.PREPARING || gameStatus == GameStatus.NOSTATE) {
            gameStatus = GameStatus.STARTING;
            if (timer != null) {
                timer.cancel();
            }
            timer = new Timer();
            timer.schedule(new TimerTask() {
                public void run() {
                    BoomView.this.nowTime += 20;
                }
            }, 0, 20);
        }
    }

    /**
     * 添加逃跑人数
     */
    public void addEscapePerson(EscapeBean escapeBean) {
        escapeBeans.add(escapeBean);
    }

    /**
     * 添加逃跑人数
     */
    public void setEscapeBeans(List<EscapeBean> escapeBeans) {
        this.escapeBeans.clear();
        this.escapeBeans.addAll(escapeBeans);
    }

    /**
     * 游戏结束
     */
    public void gameOver(float boomValue) {
        this.boomValue = boomValue;
        escapeBeans.clear();
        nowTime = 0;
        if (timer != null) {
            timer.cancel();
        }
        gameStatus = GameStatus.GAME_OVER;
    }


    /**
     * 游戏准备中
     */
    public void gamePreparing(int prepareTime) {
        if (gameStatus == GameStatus.GAME_OVER || gameStatus == GameStatus.NOSTATE || gameStatus == GameStatus.PAUSE) {
            this.prepareTime = prepareTime;
            gameStatus = GameStatus.PREPARING;
            if (timer != null) {
                timer.cancel();
            }
            timer = new Timer();
            timer.schedule(new TimerTask() {
                public void run() {
                    BoomView.this.prepareTime -= 20;
                    if (BoomView.this.prepareTime <= 0) {
                        BoomView.this.prepareTime = 0;
                    }
                }
            }, 0, 20);
        }
    }

    public Paint getLineKPaint() {
        return lineKPaint;
    }

    public Paint getLineStrokePaint() {
        return lineStrokePaint;
    }

    public Paint getLineTextPaint() {
        return lineTextPaint;
    }

    public Paint getBoomTextPaint() {
        return boomTextPaint;
    }

    public Paint getBoomValuePaint() {
        return boomValuePaint;
    }

    public Paint getLineTextScalePaint() {
        return lineTextScalePaint;
    }

    public void setCanDraw(boolean canDraw) {
        this.canDraw = canDraw;
    }

    public boolean isCanDraw() {
        return canDraw;
    }

    /**
     * 设置左边下边边界线颜色
     *
     * @param color
     */
    public void setStrokeColor(int color) {
        lineStrokePaint.setColor(color);
    }

    /**
     * 设置边框刻度值文本颜色
     *
     * @param color
     */
    public void setLineTextColor(int color) {
        lineTextPaint.setColor(color);
    }

    public GameStatus getGameStatus() {
        return gameStatus;
    }

    /**
     * 设置显示文本颜色，倒计时，倍数
     *
     * @param color
     */

    public void setShowTextColor(int color) {
        lineTextScalePaint.setColor(color);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (isFirst) {
            isFirst = false;
            timerDraw = new Timer();
            timerDraw.schedule(new TimerTask() {
                @Override
                public void run() {
                    postInvalidate();
                }
            }, 0, 20);
        }
        drawing(canvas);
    }

    private void drawing(Canvas canvas) {
        if (gameStatus == GameStatus.PAUSE) {
            return;
        }
        try {

            mCanvas = canvas;
            //这里进行内容的绘制
            if (mCanvas == null)
                return;

            if (bgColor == 0) {
                mCanvas.drawColor(Color.parseColor("#7D7DBC"));
            } else {
                mCanvas.drawColor(bgColor);
            }


            float nowTimes = getTimesByTime(nowTime);
            List<Float> scaleNumYs = getScaleNumYs();
            List<Integer> scaleNumXs = getScaleNumXs();


            //绘制左边线

            mCanvas.drawLine(startX, startY, startX, paddingTop, lineStrokePaint);
            if (canDraw) {
                for (Float scaleNumY : scaleNumYs) {
                    mCanvas.drawText(keep(scaleNumY + "", 1, true) + " x", startX - xSection / 2, getYByScale(scaleNumY), lineTextPaint);
                }
            }
            //绘制下边线
            mCanvas.drawLine(startX, startY, width - paddingEnd, startY, lineStrokePaint);
            if (canDraw) {
                for (Integer scaleNumX : scaleNumXs) {
                    float x = startX + (scaleNumX * xLenth / Math.max(minXNum, nowTime));
                    mCanvas.drawText(scaleNumX / 1000 + "", x, height - paddingBottom - ySection / 2, lineTextPaint);
                }
            }
            switch (gameStatus) {
                case STARTING:
                    if (canDraw) {
                        //绘制曲线
                        Path path = new Path();

                        int sectionNum;
                        if (nowTime < minXNum) {
                            sectionNum = (int) (nowTime / (minXNum / klineNum));
                        } else {
                            sectionNum = klineNum;
                        }
                        if (sectionNum == 0)
                            return;
                        float timeSection = nowTime / sectionNum;
                        float sectionX = xLenth / klineNum;
                        for (int i = 1; i < sectionNum; i++) {
                            float lastPointX = startX + (i - 1) * sectionX;
                            float lastPointY = getYByScale(getTimesByTime((int) (timeSection * (i - 1))));
                            float nowPointX = startX + (i) * sectionX;
                            float nowPointY = getYByScale(getTimesByTime((int) (timeSection * (i))));
                            path.moveTo(lastPointX, lastPointY);
                            path.quadTo(lastPointX, lastPointY, nowPointX, nowPointY);
                        }
                        mCanvas.drawPath(path, lineKPaint);
                        if (boomListener != null) {
                            boomListener.onTextChange(keep(nowTimes + "", 2, false));
                        }
                        mCanvas.drawText(keep(nowTimes + "", 2, false) + "X", startX + xLenth / 2, startY - yLenth / 2, lineTextScalePaint);
                        //绘制逃跑人名
                        if (escapeBeans == null || escapeBeans.size() == 0) {
                            return;
                        }
                        for (EscapeBean escapeBean : escapeBeans) {
                            escapeBean.drawName(this, mCanvas, nowTime);
                        }
                    }
//                //绘制当前X数
//                if (nowTimes > boomValue) {
//                    nowTimes = boomValue;
//                    if (boomListener != null) {
//                        boomListener.boom();
//                    }
//                    gameOver();
//
//                }
                    break;
                case GAME_OVER:
                    if (boomListener != null) {
                        boomListener.boom();
                    }
                    if (canDraw) {
                        mCanvas.drawText(context.getString(R.string.boomJavaBoomView8), startX + xLenth / 2, startY - yLenth * 2 / 3, boomTextPaint);
                        mCanvas.drawText(keep(boomValue + "", 2, false) + "X", startX + xLenth / 2, startY - yLenth * 1 / 3, boomValuePaint);
                    }
                    break;
                case PREPARING:
                    if (boomListener != null) {
                        boomListener.prePare();
                    }
                    if (canDraw) {
                        mCanvas.drawText(context.getString(R.string.boomJavaBoomView11) + keep(((float) prepareTime) / 1000 + "", 1, false) + context.getString(R.string.boomJavaBoomView13), startX + xLenth / 2, startY - yLenth / 2, lineTextScalePaint);
                    }
                    break;
            }
        } catch (Exception e) {

        }
    }

    /**
     * 根据倍数获取y高度
     *
     * @return
     */
    public float getYByScale(float times) {
        return startY - yLenth * (times - 1) / (Math.max(minYNum, getTimesByTime(nowTime)) - 1);
    }

    public void gamePause() {
        gameStatus = GameStatus.PAUSE;
    }

    public int getNowTime() {
        return nowTime;
    }

    /**
     * 以当前时间 毫秒
     *
     * @param time
     */
    public void supendStart(int time) {
        gameStatus = GameStatus.PREPARING;
        gameStart();
        gameStatus = GameStatus.STARTING;
        nowTime = time;
    }

    /**
     * 获取
     *
     * @return
     */
    private List<Float> getScaleNumYs() {
        ArrayList<Float> times = new ArrayList<>();
        float nowTimes = getTimesByTime(nowTime);
        float nowSectionY = initDegreeY;
        if (nowTimes < minYNum) {
            for (int i = 0; i < 5; i++) {
                times.add((1 + (i * 0.2f)));
            }
        } else {
            while (1 + (nowSectionY * sectionNumY) < nowTimes) {
                nowSectionY = (nowSectionY * sectionNumY);
            }
            for (int i = 0; i < (nowTimes - 1) / nowSectionY; i++) {
                times.add((1 + (i * nowSectionY)));
            }
        }
        return times;
    }

    /**
     * 根据当前时间，获取下部绘制坐标点位
     *
     * @return
     */
    private List<Integer> getScaleNumXs() {
        ArrayList<Integer> times = new ArrayList<>();
        float nowSectionX = initDegreeX;
        if (nowTime < minXNum) {
            for (int i = 0; i < minXNum / 1000 / nowSectionX; i++) {
                times.add((int) (i * nowSectionX * 1000));
            }
        } else {
            while (nowSectionX * sectionNumX * 1000 < nowTime / 2) {
                nowSectionX *= sectionNumX;
            }
            for (int i = 0; i < nowTime / 1000 / nowSectionX; i++) {
                times.add((int) (i * nowSectionX * 1000));
            }
        }
        return times;
    }

    /**
     * 根据时间获取倍数
     *
     * @param nowTime
     * @return
     */
    public float getTimesByTime(float nowTime) {
        double a = 1.0716d;
        nowTime = nowTime / 1000;
        double y = Math.pow(a, nowTime);
        y = Double.valueOf(y + "");
        if (y < 1.01) {
            y = 1.01;
        }
        return (float) y;
    }

    /**
     * 根据倍数获取时间
     *
     * @param scale
     * @return
     */
//    public float getTimeByTimes(float scale) {
//        double a=1.0716d;
//        if (scale<1.01){
//            scale= (float) 1.01;
//        }
//        Math.log()
//        return (float) (Math.sqrt((scale - 1) * 100) * 1000);
//    }
    public static float getTimeByTimes(float scale) {
        double a = 1.0716d;
        if (scale < 1.01) {
            scale = (float) 1.01;
        }
        double nowTime = Math.log(scale) / Math.log(a);
        return (float) nowTime * 1000;
    }

    /**
     * 测量
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int wSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int wSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int hSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int hSpecSize = MeasureSpec.getSize(heightMeasureSpec);

        if (wSpecMode == MeasureSpec.AT_MOST && hSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(300, 300);
        } else if (wSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(300, hSpecSize);
        } else if (hSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(wSpecSize, 300);
        }
        height = getMeasuredHeight();
        width = getMeasuredWidth();
        paddingStart = getPaddingStart();
        paddingTop = getPaddingTop();
        paddingBottom = getPaddingBottom();
        paddingEnd = getPaddingEnd();
        startX = paddingStart + xSection;
        startY = height - paddingBottom - ySection;
        xLenth = width - paddingStart - paddingEnd - xSection;
        yLenth = height - paddingTop - paddingBottom - ySection;
    }

    public void setxSection(float xSection) {
        this.xSection = xSection;
    }

    public void setySection(float ySection) {
        this.ySection = ySection;
    }

    /**
     * 根据时间获取X轴
     *
     * @param time
     */
    public float getXByTime(float time) {
        if (nowTime > minXNum) {
            return startX + time * xLenth / nowTime;
        } else {
            return startX + time * xLenth / minXNum;
        }
    }

    /**
     * 根据时间获取Y轴
     *
     * @param time
     */
    public float getYByTime(float time) {
        float times = getTimesByTime(time);
        return getYByScale(times);

    }

    public static String keep(String number, int keepNum, boolean isMax) {
        if (TextUtils.isEmpty(number)) {
            return 0 + "";
        }
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMaximumFractionDigits(keepNum);
        if (!isMax) {
            nf.setMinimumFractionDigits(keepNum);
        }
        nf.setGroupingUsed(false);
        // 如果不需要四舍五入，可以使用RoundingMode.DOWN
        nf.setRoundingMode(RoundingMode.HALF_UP);
        return nf.format(new BigDecimal(number).doubleValue());
    }

    public interface BoomListener {
        void boom();

        void prePare();

        void onTextChange(String nowTime);
    }

    @Override
    protected void onDetachedFromWindow() {

        if (timer != null) {
            timer.cancel();
            timer = null;
        }
        super.onDetachedFromWindow();
    }
}